package com.example.samchan.music_player_0;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.example.samchan.music_player_0.data.MusicList;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Stack;
import java.util.Timer;
import java.util.TimerTask;

public class PlayerService extends Service {

    // 播放器控制命令
    public static final int COMMAND_UNKNOWN = -1;
    public static final int COMMAND_PLAY = 0;
    public static final int COMMAND_PAUSE = 1;
    public static final int COMMAND_STOP = 2;
    public static final int COMMAND_RESUME = 3;
    public static final int COMMAND_PREVIOUS = 4;
    public static final int COMMAND_NEXT = 5;
    public static final int COMMAND_CHECK_IS_PLAYING = 6;
    public static final int COMMAND_SEEK_TO = 7;
    public static final int COMMAND_MODE_CHANGE = 8;
    public static final int COMMAND_UPDATE_TIME = 9;
    public static final int COMMAND_SET_SLEEP_TIME = 10;
    public static final int COMMAND_EXIT = 11;
    // 播放器状态
    public static final int STATUS_UNKNOWN = -1;
    public static final int STATUS_PLAYING = 0;
    public static final int STATUS_PAUSED = 1;
    public static final int STATUS_STOPPED = 2;
    public static final int STATUS_COMPLETED = 3;

    // 广播标识
    public static final String BROADCAST_PLAYERSERVICE_CONTROL = "PlayerService.ACTION_CONTROL";
    public static final String BROADCAST_PLAYERSERVICE_UPDATE_STATUS = "PlayerService.ACTION_UPDATE";

    // 播放状态
    private int musicIndex = 0;
    private int status;

    // 媒体播放类
    private MediaPlayer player = new MediaPlayer();

    // 广播接收器
    private CommandReceiver receiver;

    private boolean phone = false;

    // 播放循环模式
    public static final int MODE_LIST_SEQUENCE = 0;
    public static final int MODE_SINGLE_CYCLE = 1;
    public static final int MODE_LIST_CYCLE = 2;
    public static final int MODE_RANDOM = 3;
    private int playmode = 0;
    private ArrayList<Integer> randomList;
    private int randomIndex;
    // 进度条更新线程
    private Handler timeIndexUpdateHandler;

    // 睡眠模式相关
    private Timer timer_sleep;
    private static boolean isSleepModeOn = false;
    private int sleepMinutes;

    // Notification相关
    private NotificationManager manager;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        // 绑定广播接收器
        bindCommandReceiver();
        status = PlayerService.STATUS_STOPPED;
        initTimeIndexUpdateHandler();
        timeIndexUpdateHandler.sendEmptyMessage(status);
        //Toast.makeText(this, "PlayerService.onCreate()", Toast.LENGTH_LONG).show();
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(new MyPhoneListener(), PhoneStateListener.LISTEN_CALL_STATE);
    }

    @Override
    public void onDestroy() {
        sendBroadcastOnStatusChanged(STATUS_STOPPED);
        manager.cancel(0x3131);
        if (player != null) {
            player.release();
        }
        super.onDestroy();
    }

    private final class MyPhoneListener extends PhoneStateListener {
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING: {
                    if (status == PlayerService.STATUS_PLAYING) {
                        pause();
                        phone = true;
                    }
                    break;
                }case TelephonyManager.CALL_STATE_IDLE: {
                    if (phone) {
                        resume();
                        phone = false;
                    }
                    break;
                }
            }
        }
    }

    // 接收并执行广播命令
    class CommandReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            String ctrl_code = intent.getAction();

            if (BROADCAST_PLAYERSERVICE_CONTROL.equals(ctrl_code)) {
                // 获取命令
                int command = intent.getIntExtra("command", COMMAND_UNKNOWN);
                // 执行命令
                switch (command) {
                    case COMMAND_PLAY:
                        musicIndex = intent.getIntExtra("musicIndex", 0);
                        play(musicIndex);
                        break;
                    case COMMAND_PREVIOUS:
                        movePrevious();
                        break;
                    case COMMAND_NEXT:
                        moveNext();
                        break;
                    case COMMAND_PAUSE:
                        pause();
                        break;
                    case COMMAND_STOP:
                        stop();
                        break;
                    case COMMAND_RESUME:
                        resume();
                        break;
                    case COMMAND_CHECK_IS_PLAYING:
                        if (player != null && player.isPlaying()) {
                            status = STATUS_PLAYING;
                            sendBroadcastOnStatusChanged(status);
                        }
                        break;
                    case COMMAND_SEEK_TO:
                        seekTo(intent.getIntExtra("timeIndex", 0));
                        break;
                    case COMMAND_MODE_CHANGE:
                        playmode = intent.getIntExtra("playmode", MODE_LIST_SEQUENCE);
                        if (playmode == MODE_RANDOM) {
                            initRandomMode();
                        }
                        break;
                    case COMMAND_SET_SLEEP_TIME: {
                        sleepMinutes = intent.getIntExtra("newSleepTime", 0);
                        if (sleepMinutes == 0) {
                            isSleepModeOn = false;
                        } else {
                            isSleepModeOn = true;
                        }
                        sleepModeSetting(sleepMinutes, isSleepModeOn);
                        break;
                    }
                    case COMMAND_UNKNOWN: {
                        break;
                    }
                    default:
                        break;
                }
            }else if ("RESUME".equals(ctrl_code)){
                resume();
            }else if ("PAUSE".equals(ctrl_code)){
                pause();
            }else if ("PREVIOUS".equals(ctrl_code)){
                movePrevious();
            }else if ("NEXT".equals(ctrl_code)){
                moveNext();
            }else if ("CLOSE".equals(ctrl_code)){
                manager.cancel(0x3131);
                System.exit(0);
            }
        }
    }

    // 睡眠模式设置
    private void sleepModeSetting(int sleepTime, boolean isSleep) {
        final TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                sendBroadcastOnStatusChanged(status, COMMAND_EXIT);
            }
        };
        if (isSleep) {
            timer_sleep = new Timer();
            // 启动任务，time*60*1000毫秒后执行
            timer_sleep.schedule(timerTask, sleepTime * 60 * 1000);
        } else {
            timerTask.cancel();
            timer_sleep.cancel();
        }
    }

    // 进度条定时更新线程
    private void initTimeIndexUpdateHandler() {
        timeIndexUpdateHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                if (status == STATUS_PLAYING) {
                    sendBroadcastOnStatusChanged(status, COMMAND_UPDATE_TIME);
                }
                timeIndexUpdateHandler.sendEmptyMessageDelayed(status, 80);
            }
        };
    }

    // 绑定广播接收器
    private void bindCommandReceiver() {
        receiver = new CommandReceiver();
        IntentFilter filter = new IntentFilter(BROADCAST_PLAYERSERVICE_CONTROL);
        filter.addAction("RESUME");
        filter.addAction("PAUSE");
        filter.addAction("PREVIOUS");
        filter.addAction("NEXT");
        filter.addAction("CLOSE");
        registerReceiver(receiver, filter);
    }

    // 播放状态改变，发送广播
    private void sendBroadcastOnStatusChanged(int status) {
        Intent intent = new Intent(BROADCAST_PLAYERSERVICE_UPDATE_STATUS);
        intent.putExtra("status", status);
        intent.putExtra("isSleep", isSleepModeOn);
        if (isSleepModeOn) {
            intent.putExtra("sleepTime", sleepMinutes);
        }
        if (status != PlayerService.STATUS_STOPPED) {
            intent.putExtra("musicIndex", musicIndex);
            intent.putExtra("musicName", MusicList.getMusicArrayList().get(musicIndex).getMusicName());
            intent.putExtra("musicArtist", MusicList.getMusicArrayList().get(musicIndex).getMusicArtist());
            intent.putExtra("musicDuration", player.getDuration());
            intent.putExtra("musicAlbum", MusicList.getMusicArrayList().get(musicIndex).getMusicAlbum());
            intent.putExtra("timeIndex", player.getCurrentPosition());
            intent.putExtra("playmode", playmode);
        }
        sendBroadcast(intent);
    }
    private void sendBroadcastOnStatusChanged(int status, int command) {
        Intent intent = new Intent(BROADCAST_PLAYERSERVICE_UPDATE_STATUS);
        intent.putExtra("status", status);
        intent.putExtra("command", command);
        switch (command) {
            case COMMAND_UPDATE_TIME: {
                intent.putExtra("timeIndex", player.getCurrentPosition());
                break;
            }
            case COMMAND_EXIT: {
                break;
            }
        }
        sendBroadcast(intent);
    }

    // 播放结束监听器
    MediaPlayer.OnCompletionListener completionListener = new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            status = STATUS_COMPLETED;
            sendBroadcastOnStatusChanged(status);
            switch (playmode) {
                case MODE_LIST_SEQUENCE: {
                    if (musicIndex == MusicList.getMusicArrayList().size() - 1) {
                        status = STATUS_STOPPED;
                        sendBroadcastOnStatusChanged(status);
                    } else {
                        moveNext();
                    }
                    break;
                }
                case MODE_SINGLE_CYCLE: {
                    status = STATUS_PLAYING;
                    replay();
                    break;
                }
                case MODE_LIST_CYCLE: {
                    if (musicIndex == MusicList.getMusicArrayList().size() - 1) {
                        musicIndex = 0;
                        play(musicIndex);
                    } else {
                        moveNext();
                    }
                    break;
                }
                case MODE_RANDOM: {
                    moveNext();
                    break;
                }
                default: {
                    sendBroadcastOnStatusChanged(status);
                }
            }
        }
    };

    // 读取音乐文件
    private void load(int musicIndex) {
        try {
            player.reset();
            player.setDataSource(MusicList.getMusicArrayList().get(musicIndex).getMusicPath());
            player.prepare();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 注册监听器
        player.setOnCompletionListener(completionListener);
    }

    // 音乐控制功能
    private void play(int musicIndex) {
        // 停止当前播放的音乐
        if (player != null && player.isPlaying()) {
            player.stop();
        }
        // 载入即将播放的音乐
        load(musicIndex);
        // 更新UI显示的内容
        status = STATUS_PLAYING;
        sendBroadcastOnStatusChanged(status);
        // 开始播放
        player.start();
        // 更新notification
        updateNotification();
    }

    private void pause() {
        if (player.isPlaying()) {
            player.pause();
            status = PlayerService.STATUS_PAUSED;
            sendBroadcastOnStatusChanged(status);
            // 更新notification
            updateNotification();
        }
    }

    private void stop() {
        if (status != PlayerService.STATUS_STOPPED) {
            player.stop();
            status = PlayerService.STATUS_STOPPED;
            sendBroadcastOnStatusChanged(status);
            // 更新notification
            updateNotification();
        }
    }

    private void resume() {
        player.start();
        status = PlayerService.STATUS_PLAYING;
        sendBroadcastOnStatusChanged(status);
        // 更新notification
        updateNotification();
    }

    private void replay() {
        player.start();
        status = PlayerService.STATUS_PLAYING;
        sendBroadcastOnStatusChanged(status);
        // 更新notification
        updateNotification();
    }

    private void moveNext() {
        if (playmode == MODE_RANDOM) {
            // 判断边际
            if (randomIndex == (MusicList.getMusicArrayList().size() - 1)) {
                randomIndex = 0;
                musicIndex = randomList.get(randomIndex);
            } else {
                randomIndex++;
                musicIndex = randomList.get(randomIndex);
            }
        } else {
            // 判断边际
            if (musicIndex == (MusicList.getMusicArrayList().size() - 1)) {
                Toast.makeText(getApplicationContext(), R.string.tip_reach_bottom, Toast.LENGTH_SHORT).show();
                if (playmode == MODE_LIST_CYCLE) {
                    musicIndex = 0;
                }
            } else {
                ++musicIndex;
            }
        }
        play(musicIndex);
    }

    private void movePrevious() {
        if (playmode == MODE_RANDOM) {
            // 判断边际
            if (randomIndex == 0) {
                randomIndex = MusicList.getMusicArrayList().size() - 1;
                musicIndex = randomList.get(randomIndex);
            } else {
                randomIndex++;
                musicIndex = randomList.get(randomIndex);
            }
        } else {
            // 判断边际
            if (musicIndex == 0) {
                Toast.makeText(getApplicationContext(), R.string.tip_reach_top, Toast.LENGTH_SHORT).show();
                if (playmode == MODE_LIST_CYCLE) {
                    musicIndex = MusicList.getMusicArrayList().size() - 1;
                    play(musicIndex);
                }
            } else {
                --musicIndex;
                play(musicIndex);
            }
        }
    }

    private void seekTo(int timeIndex) {
        status = STATUS_PLAYING;
        sendBroadcastOnStatusChanged(status);
        player.seekTo(timeIndex);
        // 更新notification
        updateNotification();
    }

    // 随机模式初始化
    private void initRandomMode() {
        int length = MusicList.getMusicArrayList().size();
        int i;
        randomList = new ArrayList<>();
        for (i = 0; i < length; i++) {
            randomList.add(i);
        }
        // 打乱列表
        Collections.shuffle(randomList);
        // 初始化随机列表索引
        randomIndex = randomList.indexOf(musicIndex);
    }

    // notification状态更新函数
    public void updateNotification() {
        manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        // 通知渠道的id
        String id = "SimplePlayer";
        // 用户可以看到的通知渠道的名字.
        CharSequence name = "SimplePlayer_Channel";
        // 用户可以看到的通知渠道的描述
        String description = "SimplePlayer_Notification_Controller";
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel mChannel = new NotificationChannel(id, name, importance);
        // 配置通知渠道的属性
        mChannel.setDescription(description);
        // 设置通知出现时的闪灯（如果 android 设备支持的话）
        mChannel.enableLights(false);
        // 设置通知出现时的震动（如果 android 设备支持的话）
        mChannel.enableVibration(false);
        //最后在NotificationManager中创建该通知渠道
        manager.createNotificationChannel(mChannel);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, id);
        RemoteViews views = new RemoteViews(getPackageName(), R.layout.notification_controller);
        // 加载封面图
        ContentResolver resolver = this.getContentResolver();
        Uri albumCover = getMediaStoreAlbumCoverUri(
                MusicList.getMusicArrayList().get(musicIndex).getAlbumID());
        // 解析uri，判断封面是否存在
        boolean isCoverExist = true;
        try {
            resolver.openInputStream(albumCover);
        } catch (FileNotFoundException ignored) {
            isCoverExist = false;
        }
        if (isCoverExist) {
            views.setImageViewUri(R.id.nc_album_pic, albumCover);
        } else {
            views.setImageViewResource(R.id.nc_album_pic, R.mipmap.album_default_cover);
        }
        views.setTextViewText(R.id.nc_music_name, MusicList.getMusicArrayList().get(musicIndex).getMusicName());
        views.setTextViewText(R.id.nc_music_playerAndAlbum,
                MusicList.getMusicArrayList().get(musicIndex).getMusicArtist() + " - " +
                MusicList.getMusicArrayList().get(musicIndex).getMusicAlbum());

        if (status == STATUS_PLAYING) {
            views.setViewVisibility(R.id.nc_play, View.GONE);
            views.setViewVisibility(R.id.nc_pause, View.VISIBLE);
        } else {
            views.setViewVisibility(R.id.nc_play, View.VISIBLE);
            views.setViewVisibility(R.id.nc_pause, View.GONE);
        }
        views.setOnClickPendingIntent(R.id.nc_previous, pre_PendingIntent());
        views.setOnClickPendingIntent(R.id.nc_play, play_PendingIntent());
        views.setOnClickPendingIntent(R.id.nc_pause, pause_PendingIntent());
        views.setOnClickPendingIntent(R.id.nc_next, next_PendingIntent());
        views.setOnClickPendingIntent(R.id.nc_closeApp, close_PendingIntent());

        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
        builder.setContent(views)
                .setContentIntent(pi)
                .setOngoing(true)
                .setSmallIcon(R.mipmap.app_logo);

        Notification notification = builder.build();
        notification.flags = Notification.FLAG_ONGOING_EVENT;
        manager.notify(0x3131,notification);
    }

    private PendingIntent close_PendingIntent() {
        Intent intent = new Intent("CLOSE");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        return pendingIntent;
    }

    private PendingIntent next_PendingIntent() {
        Intent intent = new Intent("NEXT");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        return pendingIntent;
    }

    private PendingIntent pause_PendingIntent() {
        Intent intent = new Intent("PAUSE");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        return pendingIntent;
    }

    private PendingIntent play_PendingIntent() {
        Intent intent = new Intent("RESUME");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        return pendingIntent;
    }

    private PendingIntent pre_PendingIntent() {
        Intent intent = new Intent("PREVIOUS");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        return pendingIntent;
    }

    public static Uri getMediaStoreAlbumCoverUri(long albumId) {
        Uri artworkUri = Uri.parse("content://media/external/audio/albumart");
        return ContentUris.withAppendedId(artworkUri, albumId);
    }
}
